package com.adhere.system.controller;

import com.adhere.common.pojo.Result;
import com.adhere.security.annotation.RequirePermissions;
import com.adhere.system.pojo.*;
import com.adhere.system.service.IRbacPrivilegeService;
import com.adhere.system.service.IRbacRoleService;
import com.adhere.system.service.IRbacUserRoleService;
import com.adhere.system.service.IRbacUserService;
import com.adhere.system.pojo.dto.PasswordDto;
import com.adhere.system.pojo.vo.PageVo;
import com.adhere.system.pojo.vo.UserDetailVo;
import com.adhere.system.service.impl.RbacRoleServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户管理
 */
@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private IRbacUserService userService;

    @Autowired
    private IRbacUserRoleService userRoleService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private IRbacRoleService roleService;

    @Autowired
    private IRbacPrivilegeService privilegeService;

    private static final String PASSWORD_REG = "^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[._~!@#$^&*])[A-Za-z0-9._~!@#$^&*]{10,16}$";

    /**
     * 根据 登录的用户名 和 权限id 分页查询查询用户信息
     * @param currentPage 当前页
     * @param pageSize 每页显示的条数
     * @param loginName 登录的用户名
     * @param roleCode 角色code
     * @return 用户列表
     */
    @RequirePermissions("system:user:list")
    @GetMapping("/")
    public PageVo<RbacUser> getUserListByPage(@RequestParam(required = false, defaultValue = "1") Integer currentPage,
                                              @RequestParam(required = false, defaultValue = "10") Integer pageSize,
                                              @RequestParam(required = false) String loginName,
                                              @RequestParam(required = false) String roleCode) {
        return userService.getUserListByPage(currentPage, pageSize, loginName, roleCode);
    }

    /**
     * 根据用户 code 查询用户 给编辑页面使用
     * @param userCode 用户code
     * @return user 用户对象
     */
    @GetMapping("/{userCode}")
    public RbacUser getUserByCode(@PathVariable String userCode) {
        QueryWrapper<RbacUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", userCode);
        return userService.getOne(queryWrapper);
    }

    /**
     * 根据 userCode 逻辑删除用户
     * @param userCode 用户code
     */
    @DeleteMapping("/{userCode}")
    public void deleteUser (@PathVariable String userCode) {
        // 校验 用户是否还拥有关联角色信息
        List<RbacUserRole> rbacUserRoleList = userRoleService.selectByUserCode(userCode);
        if (!rbacUserRoleList.isEmpty()) {
            throw new IllegalArgumentException("此用户还有关联的角色信息，请先解除绑定");
        }

        UpdateWrapper<RbacUser> updateWrapper = new UpdateWrapper<>();
        // 0 表示未删除  1 表示已删除
        updateWrapper.eq("code", userCode);
        updateWrapper.set("is_deleted", 1);
        userService.update(updateWrapper);
    }

    /**
     * 锁定用户信息
     * @param userCode 用户code
     * @param isLocked 是否锁定用户 true锁定
     */
    @PutMapping("/lock/{userCode}")
    public void lockUser (@PathVariable String userCode,@RequestParam boolean isLocked) {
        UpdateWrapper<RbacUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("code", userCode);
        updateWrapper.set("is_locked", isLocked);
        userService.update(updateWrapper);
    }

    /**
     * 管理员重置用户密码
     * @param userCode 用户code
     * @param passwordDto 用户新的密码
     */
    @PutMapping("/password/{userCode}")
    public void updatePassword (@RequestBody PasswordDto passwordDto, @PathVariable(name = "userCode") String userCode) {
        String newPassword = passwordDto.getNewPassword();
        if (!StringUtils.hasText(newPassword) || newPassword.length() < 10 || newPassword.length() > 16) {
            throw new IllegalArgumentException("密码的长度应该在10-16位之间");
        }
        if (!newPassword.matches(PASSWORD_REG)) {
            throw new IllegalArgumentException("密码应是大小字母,数字,特殊字符的混合体,不能包含公司信息，长度在10-16位之间");
        }

        UpdateWrapper<RbacUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("code", userCode);
        updateWrapper.set("password", passwordEncoder.encode(newPassword));
        userService.update(updateWrapper);
    }

    /**
     * 用户重置自己的密码
     * @param passwordDto 密码的信息类
     * @param userCode 用户code
     */
    @PutMapping("/password/self/{userCode}")
    public void updatePasswordBySelf (@RequestBody @Validated PasswordDto passwordDto,
                                @PathVariable(name = "userCode") String userCode) {

        String newPassword = passwordDto.getNewPassword();
        String oldPassword = passwordDto.getOldPassword();
        if (!StringUtils.hasText(newPassword) || newPassword.length() < 10 || newPassword.length() > 16) {
            throw new IllegalArgumentException("密码的长度应该在10-16位之间");
        }
        if (oldPassword.equals(newPassword)) {
            throw new IllegalArgumentException("您输入的新密码和旧密码相同");
        }
        if (!newPassword.matches(PASSWORD_REG)) {
            throw new IllegalArgumentException("密码应是大小字母,数字,特殊字符的混合体,不能包含公司信息，长度在10-16位之间");
        }

        // 校验旧密码
        QueryWrapper<RbacUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", userCode);
        RbacUser user = userService.getOne(queryWrapper);
        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            throw new IllegalArgumentException("原密码输入错误");
        }
        UpdateWrapper<RbacUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("code", userCode);
        updateWrapper.set("password", passwordEncoder.encode(passwordDto.getNewPassword()));
        userService.update(updateWrapper);
    }

    /**
     * 修改用户信息
     * @param user 用户实体类对象
     */
    @PutMapping("/")
    public void updateUser (@RequestBody RbacUser user) {
        Assert.notNull(user.getCode(), "修改用户时,用户的code不能为空");
        String userCode = user.getCode();
        QueryWrapper<RbacUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.ne("code", userCode);
        queryWrapper.eq("login_name", user.getLoginName());
        RbacUser userRepeat = userService.getOne(queryWrapper);
        if (userRepeat != null) {
            throw new IllegalArgumentException("登录名已经存在！");
        }
        UpdateWrapper<RbacUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("code", userCode);
        userService.update(user,updateWrapper);
    }

    /**
     * 重置手机号
     * @param userCode 用户编码
     * @param newPhoneNumber 新的手机号
     */
    @PutMapping("/phone/{userCode}")
    public void updatePhoneNumber (@PathVariable String userCode, String newPhoneNumber) {
        UpdateWrapper<RbacUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("code", userCode);
        updateWrapper.set("msisdn", newPhoneNumber);
        userService.update(updateWrapper);
    }

    /**
     * 添加用户信息
     * @param user 用户实体类信息
     */
    @PostMapping("/")
    public void addUser (@RequestBody @Validated RbacUser user) {
        String newPassword = user.getPassword();
        if (!StringUtils.hasText(newPassword) || newPassword.length() < 10 || newPassword.length() > 16) {
            throw new IllegalArgumentException("密码的长度应该在10-16位之间");
        }
        if (!newPassword.matches(PASSWORD_REG)) {
            throw new IllegalArgumentException("密码应是大小字母,数字,特殊字符的混合体,不能包含公司信息，长度在10-16位之间");
        }
        userService.addUser(user);
    }

    /**
     * 根据登录名查询 用户和用户的角色列表  认证服务器使用 返回了密码的
     * @param loginName 登陆名
     * @return
     */
    @GetMapping("/detail")
    public UserDetailVo getUserDetailByUserName(@RequestParam(required = true) String loginName) {
        return userService.getUserDetailByUserName(loginName);
    }

    /**
     * 根据用户名查询用户的基本信息
     * @param loginName 登录名
     * @return RbacUser 用户信息
     */
    @GetMapping("/basic")
    public RbacUser getUserByBasic (@RequestParam String loginName) {
        QueryWrapper<RbacUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("login_name", loginName);
        return userService.getOne(queryWrapper);
    }

    /**
     * 根据用户名查询用户的基本信息
     * @param loginName 登录名
     * @return RbacUser 用户信息
     */
    @GetMapping("/login/{loginName}")
    public Result<LoginUser> getUserByLoginName (@PathVariable String loginName) {
        QueryWrapper<RbacUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("login_name", loginName);
        RbacUser rbacUser = userService.getOne(queryWrapper);
        // todo 先暂时这样写，后面可以改成联表，或者修改数据库结构适配现在这套鉴权系统
        String code = rbacUser.getCode();
        List<RbacRole> roleList = roleService.getRoleListByUserCode(code);
        List<RbacPrivilege> privilegeList = privilegeService.getPrivilegeListByUserCode(code);
        LoginUser loginUser = new LoginUser()
                .setRbacUser(rbacUser)
                .setRoles(roleList.stream().map(RbacRole::getName).collect(Collectors.toSet()))
                .setPermissions(privilegeList.stream().map(RbacPrivilege::getUri).collect(Collectors.toSet()));

        return Result.success(loginUser);
    }


    /**
     * 根据查询 用户code和用户的角色列表
     * @param userCode 用户编码
     * @return UserDetailVo
     */
    @GetMapping("/detail/")
    public UserDetailVo getUserDetailByUserCode(@RequestParam(required = true) String userCode) {
        return userService.getUserDetailByUserCode(userCode);
    }

    /**
     * 查询所有拥有管理员角色的用户
     * @return
     */
    @GetMapping("/admin")
    public List<RbacUser> getUserWithAdmin () {
        return userService.getUserWithAdmin();
    }


}
